package com.baidu.infinity.ui.fragment.home

import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.content.BroadcastReceiver
import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.Bitmap
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import android.text.Editable
import android.text.TextWatcher
import android.view.Gravity
import android.view.View
import android.view.WindowManager.LayoutParams
import android.widget.LinearLayout
import android.widget.PopupWindow
import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat
import androidx.core.content.ContextCompat.registerReceiver
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat.Type
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import com.baidu.infinity.R
import com.baidu.infinity.databinding.FragmentHomeBinding
import com.baidu.infinity.databinding.LayoutHsvcolorpickerViewBinding
import com.baidu.infinity.databinding.LayoutLayerItemBinding
import com.baidu.infinity.databinding.LayoutLayerShowViewBinding
import com.baidu.infinity.model.IconModel
import com.baidu.infinity.model.LayerModel
import com.baidu.infinity.ui.base.BaseFragment
import com.baidu.infinity.ui.fragment.home.shape.LayerManager
import com.baidu.infinity.ui.fragment.home.view.LoadAnimPopUpWindow
import com.baidu.infinity.ui.fragment.home.view.backgroundpopupview.BackgroundPopUpWindow
import com.baidu.infinity.ui.fragment.home.view.strokesize.StrokeBarView
import com.baidu.infinity.ui.util.state.IconState
import com.baidu.infinity.ui.util.LayerModelManager
import com.baidu.infinity.ui.util.state.LayerState
import com.baidu.infinity.ui.util.OperationType
import com.baidu.infinity.ui.util.delayTask
import com.baidu.infinity.ui.util.getCurrentTime
import com.drake.brv.BindingAdapter
import com.drake.brv.listener.DefaultItemTouchCallback
import com.drake.brv.utils.linear
import com.drake.brv.utils.models
import com.drake.brv.utils.setup
import kotlinx.coroutines.launch

@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
class HomeFragment : BaseFragment<FragmentHomeBinding>(){
    private val iconClickReceiver: IconClickReceiver = IconClickReceiver()
    private var isMenuDrawOpen = true
    private var isMenuOpen = true
    private val menuDrawOpenBottom by lazy {
        mBinding.menuDrawViewLayout.bottom
    }
    private val menuDrawCloseBottom by lazy {
        mBinding.menuDrawViewLayout.top + mBinding.menuBtn.bottom
    }
    private val menuOpenLeft by lazy {
        mBinding.menuView.left
    }
    private val menuCloseLeft by lazy {
        mBinding.menuView.right
    }
    private val menuOperationOpenLeft by lazy {
        mBinding.menuOperationView.left
    }
    private val menuOperationCloseLeft by lazy {
        mBinding.root.right
    }
    private val menuDrawCloseAnimatorSet: AnimatorSet by lazy {
        val r = ObjectAnimator.ofFloat(
            mBinding.menuBtn,
            "rotation",
            0f,360f
        )
        val m = ObjectAnimator.ofInt(
            mBinding.menuDrawViewLayout,
            "bottom",
            menuDrawOpenBottom,menuDrawCloseBottom
        )
        AnimatorSet().apply {
            playTogether(r,m)
        }
    }
    private val menuDrawOpenAnimatorSet: AnimatorSet by lazy {
        val r = ObjectAnimator.ofFloat(
            mBinding.menuBtn,
            "rotation",
            0f,-360f
        )
        val m = ObjectAnimator.ofInt(
            mBinding.menuDrawViewLayout,
            "bottom",
            menuDrawCloseBottom,menuDrawOpenBottom
        )
        AnimatorSet().apply {
            playTogether(r,m)
        }
    }
    private val menuCloseAnimatorSet: AnimatorSet by lazy {
        val r = ObjectAnimator.ofFloat(
            mBinding.menuArrow,
            "rotation",
            0f,180f
        )
        val m = ObjectAnimator.ofInt(
            mBinding.menuView,
            "left",
            menuOpenLeft,menuCloseLeft
        )
        AnimatorSet().apply {
            playTogether(r,m)
        }
    }
    private val menuOpenAnimatorSet: AnimatorSet by lazy {
        val r = ObjectAnimator.ofFloat(
            mBinding.menuArrow,
            "rotation",
            180f,360f
        )
        val m = ObjectAnimator.ofInt(
            mBinding.menuView,
            "left",
            menuCloseLeft,menuOpenLeft
        )
        AnimatorSet().apply {
            playTogether(r,m)
        }
    }
    private val menuOperationOpenAnimator: ObjectAnimator by lazy {
        ObjectAnimator.ofInt(
            mBinding.menuOperationView,
            "left",
            menuOperationCloseLeft,menuOperationOpenLeft
        )
    }
    private val menuOperationCloseAnimator: ObjectAnimator by lazy {
        ObjectAnimator.ofInt(
            mBinding.menuOperationView,
            "left",
            menuOperationOpenLeft,menuOperationCloseLeft
        )
    }
    private val mBackgroundPopUpWindow: BackgroundPopUpWindow by lazy {
        BackgroundPopUpWindow(requireContext())
    }
    private val mLoadAnimPopUpWindow: LoadAnimPopUpWindow by lazy {
        LoadAnimPopUpWindow(requireContext())
    }
    private val mPopupWindow by lazy {
        val popUpWindow = PopupWindow(requireContext())
        val hsvPickerBinding = LayoutHsvcolorpickerViewBinding.inflate(layoutInflater)
        val view = hsvPickerBinding.root
        view.addColorChangeListener { color: Int ->
            LayerManager.instance.mColor = color
            mBinding.drawView.reDraw()
        }
        popUpWindow.contentView = view
        popUpWindow.width = LayoutParams.WRAP_CONTENT
        popUpWindow.height = LayoutParams.WRAP_CONTENT
        popUpWindow.isFocusable = false
        popUpWindow
    }

    private var isShowColorOicker = false
    private var isShowStrokeSizeView = false
    private var isShowLayerPopupView = false
    private var isShowBackgroundPopupView = false
    private var mLayerPopupWindowBinding: LayoutLayerShowViewBinding ?= null
    private val mLayerPopupWindow by lazy {
        val popUpWindow = PopupWindow(requireContext())
        mLayerPopupWindowBinding = LayoutLayerShowViewBinding.inflate(layoutInflater)
        mLayerPopupWindowBinding!!.addLayerBtn.setOnClickListener{
            LayerManager.instance.addLayer(mBinding.drawView.width,mBinding.drawView.height)
            refreshLayer()
        }
        mLayerPopupWindowBinding!!.recyclerView.linear().setup {
            addType<LayerModel>(R.layout.layout_layer_item)
            onBind {
                val layerModelBinding = getBinding<LayoutLayerItemBinding>()
                val data = getModel<LayerModel>()
                layerModelBinding.imageView.setOnClickListener{
                    LayerModelManager.instance.selectLayer(data)
                    refreshLayer()
                }
                layerModelBinding.imageView.setImageBitmap(data.bitmap)
                if(data.state == LayerState.NORMAL){
                    layerModelBinding.selectView.visibility = View.INVISIBLE
                }else{
                    layerModelBinding.selectView.visibility = View.VISIBLE
                }


            }
            itemTouchHelper = ItemTouchHelper(object : DefaultItemTouchCallback() {
                override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
                    super.onSwiped(viewHolder, direction)
                    val model = (viewHolder as BindingAdapter.BindingViewHolder).getModel<LayerModel>()
                    refreshLayer()
                    LayerManager.instance.removeLayer(model.id)
                    mBinding.drawView.reDraw()

                }
                override fun onDrag(
                    source: BindingAdapter.BindingViewHolder,
                    target: BindingAdapter.BindingViewHolder
                ) {
                    super.onDrag(source, target)
                    val sourceModel = source.getModel<LayerModel>()
                    val targetModel = target.getModel<LayerModel>()
                    LayerManager.instance.switchLayer(sourceModel.id,targetModel.id)
                    mBinding.drawView.reDraw()
                }



            })
        }.models = LayerModelManager.instance.getLayerData()

        val view = mLayerPopupWindowBinding!!.root
        popUpWindow.contentView = view
        popUpWindow.width = LayoutParams.WRAP_CONTENT
        popUpWindow.height = LayoutParams.WRAP_CONTENT
        popUpWindow.isFocusable = false
        popUpWindow
    }
    private val mStrokePopupWindow by lazy {
        val popUpWindow = PopupWindow(requireContext())
        popUpWindow.contentView = StrokeBarView(requireContext())
        popUpWindow.width = LayoutParams.WRAP_CONTENT
        popUpWindow.height = LayoutParams.WRAP_CONTENT
        popUpWindow.isFocusable = false
        popUpWindow
    }

    override fun initUI(savedInstanceState: Bundle?) {
        super.initUI(savedInstanceState)

        LayerManager.instance.init(requireContext().applicationContext)
        initReceiver()
        initMenuDraw()
        initMenu()
        initMenuOperation()
        initEvent()
        mBinding.drawView.setEndPointListener = {
            refreshLayer()
        }
    }


    override fun onDestroy() {
        super.onDestroy()
        requireContext().unregisterReceiver(
            iconClickReceiver
        )
    }
    @SuppressLint("ResourceType")
    fun initMenuDraw(){
        val menuString = resources.getString(R.string.menu)
        val menuModel = IconModel(
            menuString,
            OperationType.DRAW_MENU,
            R.color.light_red,
            R.color.light_red
        )
        mBinding.menuBtn.setIconModel(menuModel)
        val menuStrings = resources.getStringArray(R.array.draw_shapes)
        val modelList = ArrayList<IconModel>()
        for (i in 1..menuStrings.size){
            val model = IconModel(
                menuStrings[i-1],
                OperationType.entries[i]
            )
            modelList.add(model)
        }
        mBinding.menuDrawView.orientation = LinearLayout.VERTICAL
        mBinding.menuDrawView.setIconModels(modelList)
    }
    @SuppressLint("ResourceType")
    fun initMenu(){
        val menus = resources.getStringArray(R.array.menus)
        val modelList = ArrayList<IconModel>()
        for (i in 13..menus.size + 12){
            val model = IconModel(
                menus[i-13],
                OperationType.entries[i]
            )
            modelList.add(model)
        }
        mBinding.menuView.orientation = LinearLayout.HORIZONTAL
        mBinding.menuView.setIconModels(modelList)
    }
    @SuppressLint("ResourceType")
    fun initMenuOperation(){
        val menuOperations = resources.getStringArray(R.array.draw_tools)
        val modelList = ArrayList<IconModel>()
        for (i in 19..menuOperations.size + 18){
            val model = IconModel(
                menuOperations[i-19],
                OperationType.entries[i]
            )
            modelList.add(model)
        }
        mBinding.menuOperationView.orientation = LinearLayout.VERTICAL
        mBinding.menuOperationView.setIconModels(modelList)
    }

    private fun initReceiver(){
        val intentFilter = IntentFilter()
        intentFilter.addAction("icon_click")
        registerReceiver(
            context,
            iconClickReceiver,
            intentFilter,
            ContextCompat.RECEIVER_NOT_EXPORTED
        )
    }
    private fun initEvent(){
        mBinding.menuBtn.setOnCustomClick{
            val intent = Intent()
            intent.action = "icon_click"
            intent.setPackage("com.baidu.infinity")
            //匹配调色板
            intent.putExtra("model",IconModel(

                "&#xe615;",
                OperationType.OPERATION_PALETTE,
                R.color.middle_black,
                R.color.light_blue,
                IconState.NORMAL
            ))
            requireContext().sendBroadcast(intent)
            val intentPencil = Intent()
            intentPencil.action = "icon_click"
            intentPencil.setPackage("com.baidu.infinity")
            //匹配调色板
            intentPencil.putExtra("model",IconModel(

                "&#xe6d9;",
                OperationType.OPERATION_PENCIL,
                R.color.middle_black,
                R.color.light_blue,
                IconState.NORMAL
            ))
            requireContext().sendBroadcast(intentPencil)

            if(menuDrawOpenAnimatorSet.isRunning || menuDrawCloseAnimatorSet.isRunning || menuOperationOpenAnimator.isRunning || menuOperationCloseAnimator.isRunning){
                return@setOnCustomClick
            }else{
                if(isMenuDrawOpen){
                    menuDrawCloseAnimatorSet.start()
                    menuOperationCloseAnimator.start()
                }else{
                    menuDrawOpenAnimatorSet.start()
                    menuOperationOpenAnimator.start()
                }
                isMenuDrawOpen = !isMenuDrawOpen
            }
        }
        mBinding.menuArrow.setOnClickListener{
            val intent = Intent()
            intent.action = "icon_click"
            intent.setPackage("com.baidu.infinity")
            intent.putExtra("model",IconModel(
                "",
                OperationType.MENU_LAYER,
                R.color.middle_black,
                R.color.light_blue,
                IconState.NORMAL
            ))
            requireContext().sendBroadcast(intent)
            val intentPicture = Intent()
            intentPicture.action = "icon_click"
            intentPicture.setPackage("com.baidu.infinity")
            //匹配调色板
            intentPicture.putExtra("model",IconModel(

                "",
                OperationType.MENU_PICTURE,
                R.color.middle_black,
                R.color.light_blue,
                IconState.NORMAL
            ))
            requireContext().sendBroadcast(intentPicture)
            if(menuOpenAnimatorSet.isRunning || menuCloseAnimatorSet.isRunning)return@setOnClickListener
            if(isMenuOpen){
                menuCloseAnimatorSet.start()
            }else{
                menuOpenAnimatorSet.start()
            }
            isMenuOpen = !isMenuOpen
        }
        mBinding.editText.addTextChangedListener(object : TextWatcher{
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                if(mBinding.drawView.mOperationType == OperationType.DRAW_TEXT){
                    LayerManager.instance.changeText(s.toString())
                    mBinding.drawView.reDraw()
                }

            }

            override fun afterTextChanged(s: Editable?) {}

        })
        mBinding.drawView.setKeyboardListener = {state ->
            if(state){
                mBinding.editText.requestFocus()
                showKeyboard()
                mBinding.editText.setText("")
            }else{
                mBinding.editText.clearFocus()
                hideKeyboard()
            }
        }
        mBackgroundPopUpWindow.addBackgroundChangeListener = {resId ->
            mBinding.drawView.setBackgroundBitmap(resId)
        }
    }
    fun refreshLayer(){
        if(mLayerPopupWindowBinding != null){
            mLayerPopupWindowBinding!!.recyclerView.models = LayerModelManager.instance.getLayerData()
        }

    }
    fun showColorPicker(){
        mPopupWindow.showAtLocation(mBinding.root,Gravity.END,mBinding.root.right - mBinding.menuOperationView.left,mBinding.root.height / 2)
    }
    fun hideColorPicker(){
        mPopupWindow.dismiss()
    }
    fun showLayerPopView(){
        mLayerPopupWindow.showAsDropDown(mBinding.menuView,-mBinding.menuOperationView.width*3,0,Gravity.END)
    }
    fun hideLayerPopView(){
        mLayerPopupWindow.dismiss()
    }
    fun showStrokePopView(){
        mStrokePopupWindow.showAsDropDown(mBinding.menuOperationView,-mBinding.menuOperationView.width * 2,-mBinding.menuOperationView.height,Gravity.LEFT)
    }
    fun hideStrokePopView(){
        mStrokePopupWindow.dismiss()
    }
    fun showKeyboard(){
        val insetsController = WindowCompat.getInsetsController(requireActivity().window,mBinding.editText)
        insetsController.show(Type.ime())
    }
    fun hideKeyboard(){
        val insetsController = WindowCompat.getInsetsController(requireActivity().window,mBinding.editText)
        insetsController.hide(Type.ime())
    }
    inner class IconClickReceiver:BroadcastReceiver(){
        override fun onReceive(context: Context?, intent: Intent?) {
            val model = intent?.getParcelableExtra("model",IconModel::class.java)
            val type = model?.type!!
            if(mBinding.drawView.mOperationType != OperationType.NONE){
                mBinding.drawView.cancelLastShapeEdit()
            }
            if(model.type.ordinal in 1..12){
                mBinding.menuDrawView.changeCurrentSelectedIcon(model.type)
                mBinding.drawView.mOperationType = type

            }else if(model.type.ordinal in 13..18){
                mBinding.menuView.changeCurrentSelectedIcon(model.type)
                when(model.type){
                    OperationType.MENU_LAYER -> {
                        if(!isShowLayerPopupView && isMenuOpen){
                            //匹配预览图层
                            if(model.iconName == ""){
                                delayTask(500){
                                    showLayerPopView()
                                }
                            }else{
                                showLayerPopView()
                            }

                        }else{
                            hideLayerPopView()
                        }
                        isShowLayerPopupView = !isShowLayerPopupView
                    }
                    OperationType.MENU_PICTURE -> {
                        if(!isShowBackgroundPopupView && isMenuOpen){
                            //匹配预览图层
                            if(model.iconName != "") {
                                mBackgroundPopUpWindow.showAsDropDown(
                                    mBinding.menuView,
                                    mBinding.menuView.width / 2,
                                    0,
                                    Gravity.BOTTOM
                                )
                            }else{
                                isShowBackgroundPopupView = true
                            }

                        }else{
                            mBackgroundPopUpWindow.hide()
                        }
                        isShowBackgroundPopupView = !isShowBackgroundPopupView
                    }
                    OperationType.MENU_DOWNLOAD -> {
                        mLoadAnimPopUpWindow.showAtLocation(mBinding.root)
                        lifecycleScope.launch {
                            mBinding.drawView.getBitmap().collect{bitmap ->
                                val fileUri = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
                                val contentValues = ContentValues().apply {
                                    put(MediaStore.Images.Media.DISPLAY_NAME, getCurrentTime())
                                    put(MediaStore.Images.Media.WIDTH,"${bitmap.width}")
                                    put(MediaStore.Images.Media.HEIGHT,"${bitmap.height}")
                                    put(MediaStore.Images.Media.MIME_TYPE,"image/jpeg")
                                }
                                val imageUri = requireContext().contentResolver.insert(fileUri,contentValues)
                                imageUri?.let {
                                    requireContext().contentResolver.openOutputStream(imageUri)?.use {
                                        bitmap.compress(Bitmap.CompressFormat.JPEG,100,it)
                                    }
                                    delayTask(500){
                                        mLoadAnimPopUpWindow.playOkAnim()
                                    }
                                }

                            }
                        }
                        mBinding.drawView.reDraw()
                        refreshLayer()
                        mBinding.menuView.cancelSelect(model.type)
                    }

                    else -> {
                        hideLayerPopView()
                    }
                }
            }else if(model.type.ordinal > 18){
                if(model.type != OperationType.OPERATION_UNDO && model.type != OperationType.OPERATION_DELETE){
                    mBinding.menuView.changeCurrentSelectedIcon(model.type)
                }
                when(model.type){
                    OperationType.OPERATION_PALETTE -> {
                        if(!isShowColorOicker && isMenuDrawOpen){
                            //匹配调色板
                            if(model.iconName == "&#xe615;"){
                                delayTask(500){
                                    showColorPicker()
                                }
                            }else{
                                showColorPicker()
                            }

                        }else{
                            hideColorPicker()
                        }
                        isShowColorOicker = !isShowColorOicker
                    }
                    OperationType.OPERATION_UNDO -> {
                        LayerManager.instance.undo()
                        mBinding.drawView.reDraw()
                        refreshLayer()
                        mBinding.menuOperationView.cancelSelect(model.type)
                    }
                    OperationType.OPERATION_DELETE -> {
                        LayerManager.instance.clear()
                        mBinding.drawView.reDraw()
                        refreshLayer()
                        mBinding.menuOperationView.cancelSelect(model.type)
                    }
                    OperationType.OPERATION_PENCIL -> {
                        if(!isShowStrokeSizeView && isMenuDrawOpen){
                            if(model.iconName == "&#xe6d9;"){
                                delayTask(500){
                                    showStrokePopView()
                                }
                            }else{
                                showStrokePopView()
                            }

                        }else{
                            hideStrokePopView()
                        }
                        isShowStrokeSizeView = !isShowStrokeSizeView
                    }
                    else -> {}
                }
            }

        }

    }

}